import 'dart:convert';

import 'package:json2entity/json2entity.dart';
import 'package:json2entity/src/zip_map.dart';
import 'package:test/test.dart';

var jsonList = '''[{"a":null,"b":1,"c":"OK","d":{"e":0},"g":[{"h":1},{"j":3}]},
               {"a":true,"b":1,"d":{"f":1},"g":[{"i":2},{"k":4}]}]''';
var jsonMap =
    '''{"root":[{"a":null,"b":1,"c":"OK","d":{"e":0},"g":[{"h":1},{"j":3}]},
                            {"a":true,"b":1,"d":{"f":1},"g":[{"i":2},{"k":4}]}]}''';

var jsonFromJuejin =
    '{"data":{"articleFeed":{"items":{"edges":[{"node":{"id":"5d3f84376fb9a06b2c326988","commentsCount":10,"hot":false,"hotIndex":161.2088,"original":true,"originalUrl":"https://juejin.im/post/5d3f8402f265da039e129574","rankIndex":23.480145447961,"screenshot":"","content":"为了保证的可读性，本文采用意译而非直译。 BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值。在对大整数执行数学运算时，以任意精度表示整数的能力尤为重要。使用BigInt，整数溢出将不再是问题。 此外，可以安全地使用更加准确时间戳，大整数ID等，而无需使用…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"55964d83e4b08a686cc6b353","title":"JavaScript"},{"id":"55c1748160b28fd99e49ea68","title":"程序员"}],"title":"JS 即将到来的第八种基本类型:BigInt","type":"post","user":{"id":"59df61ec51882578ce26ee6e","role":"guest","avatarHd":null,"avatarLarge":"https://mirror-gold-cdn.xitu.io/168e08a02f4dda88289","username":"前端小智"},"lastCommentTime":"2019-07-30T10:24:11.927Z","likeCount":25,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-29T23:41:43.557Z","updatedAt":"2019-07-30T02:30:00.069Z"}},{"node":{"id":"5d3f89e3e51d4561e36ad9d3","commentsCount":4,"hot":false,"hotIndex":36.1599,"original":true,"originalUrl":"https://juejin.im/post/5d3f1664e51d4561a34618c1","rankIndex":19.95481916402,"screenshot":"https://user-gold-cdn.xitu.io/2019/7/30/16c3e7c9302aaf7d?w=1366&h=768&f=jpeg&s=245350","content":"文件操作是开发过程中并不可少的一部分。Node.js 中的 fs 模块是文件操作的封装，它提供了文件读取、写入、更名、删除、遍历目录、链接等 POSIX 文件系统操作。与其它模块不同的是，fs 模块中所有的操作都提供了异步和同步的两个版本,具有 sync 后缀的方法为同步方法，…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"55964d83e4b08a686cc6b353","title":"JavaScript"}],"title":"Node.js 高级进阶之 fs 文件模块学习","type":"post","user":{"id":"5cf288385188254abb110e3b","role":"guest","avatarHd":null,"avatarLarge":"https://mirror-gold-cdn.xitu.io/16b1364249167f0265d","username":"大西轰已在服务区"},"lastCommentTime":"2019-07-30T10:19:37.998Z","likeCount":16,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:37:58.718Z","updatedAt":"2019-07-30T02:29:39.738Z"}},{"node":{"id":"5d3f94d3e51d4561ac7bcc43","commentsCount":6,"hot":false,"hotIndex":60.0742,"original":false,"originalUrl":"https://mp.weixin.qq.com/s/fQ98fe3XH6imxzNhwiNaNA","rankIndex":16.826788179048,"screenshot":null,"content":"中台最近又成了比较热的话题，结合我对中台的认知，试图跟你回答下这些问题：1.互联网公司的中台到底是什么？2.中台有哪些类型？3.中台有哪些困境？4.互联网公司中台的现状 5.关于中台的建议 1 中台化据说是马云参观 Supercell 后在阿里巴巴提出的，要求“大中台、小前台”…","summaryInfo":null,"category":{"name":"阅读","id":"5562b428e4b00c57d9b94b9d"},"tags":[{"id":"5597a063e4b08a686ce57030","title":"后端"},{"id":"5597a05ae4b08a686ce56f6f","title":"前端"},{"id":"56e65334da2f60004c50910f","title":"产品"},{"id":"55cdb52740ac79db3570607f","title":"架构"}],"title":"我看中台","type":"article","user":{"id":"551d677ee4b0cd5b623f49cb","role":"admin","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2019/3/22/169a1107d352a82b?w=1122&h=1125&f=png&s=1034504","username":"阴明"},"lastCommentTime":"2019-07-30T10:06:30.497Z","likeCount":21,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T00:52:35.927Z","updatedAt":"2019-07-30T02:32:11.636Z"}},{"node":{"id":"5d3f9cf9f265da03b12025f1","commentsCount":2,"hot":false,"hotIndex":32.4122,"original":true,"originalUrl":"https://juejin.im/post/5d3f9cc1f265da03a31d1192","rankIndex":14.448128155325,"screenshot":"","content":"最近在公司做了几张报表，还记得刚开始要做报表的时候都快把SQL给忘光了（当时在广州休假了1个月多，在实习期间也没咋写过SQL），回到公司的第一个需求就是做报表。 于是我很不要脸地跟带我的学长说：“SQL我好像忘光了，group 分组查询好像都忘得差不多了，我得复习一下”。 gr…","summaryInfo":null,"category":{"name":"后端","id":"5562b419e4b00c57d9b94ae2"},"tags":[{"id":"555e9a8de4b00c57d9955eb9","title":"MySQL"},{"id":"559a7207e4b08a686d25703e","title":"Java"}],"title":"在工作中常用到的SQL","type":"post","user":{"id":"5a7005b46fb9a01c995117a7","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2018/4/9/162a82f18292cf7f?w=599&h=556&f=jpeg&s=41708","username":"Java3y"},"lastCommentTime":"2019-07-30T10:32:25.594Z","likeCount":9,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:27:21.717Z","updatedAt":"2019-07-30T02:32:28.024Z"}},{"node":{"id":"5d3f95bc6fb9a06b065c4d29","commentsCount":1,"hot":false,"hotIndex":31.6235,"original":false,"originalUrl":"https://mp.weixin.qq.com/s/1Er03vNkqEnTm7uytQ4b0w","rankIndex":11.889829088061,"screenshot":"","content":"各种秋招福利，我这里都有～","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[],"title":"阿里秋招提前开启！","type":"article","user":{"id":"59be059c5188256c6d77cf2e","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2017/12/18/1606900c1392ea33?w=2122&h=1406&f=jpeg&s=486693","username":"Neal_yang"},"lastCommentTime":"2019-07-30T09:50:06.645Z","likeCount":2,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T00:56:28.374Z","updatedAt":"2019-07-30T02:22:11.634Z"}},{"node":{"id":"5d3ed1fce51d4561ea1a93be","commentsCount":24,"hot":false,"hotIndex":771.7771,"original":true,"originalUrl":"https://juejin.im/post/5d3eca78e51d4561cb5dde12","rankIndex":11.707039881254,"screenshot":"","content":"本文的每一条，都是我曾经发过的掘金沸点，其中有很多条超过了百赞（窃喜）。 鉴于时不时有童鞋翻我以前的沸点，因此，本文收集了个人目前发过的所有CSS知识点动图，以便阅读。 需要说明的是，顺序仍是按当时发布顺序罗列的，还没有系统的总结，多多包涵。 另外这里，老姚谢谢各位一如既往的支…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"555eadc1e4b00c57d9962402","title":"CSS"},{"id":"55964d83e4b08a686cc6b353","title":"JavaScript"}],"title":"你未必知道的49个CSS知识点","type":"post","user":{"id":"58247e285bbb5000590e4824","role":"editor","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2017/7/6/b10fb92f65f744347fea909a8ccabfa0","username":"老姚"},"lastCommentTime":"2019-07-30T10:27:11.132Z","likeCount":456,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-29T11:01:16.291Z","updatedAt":"2019-07-30T02:32:10.639Z"}},{"node":{"id":"5d3ed351f265da03b94fcc95","commentsCount":4,"hot":false,"hotIndex":21.2803,"original":true,"originalUrl":"https://juejin.im/post/5d3ed167f265da03e71acd64","rankIndex":11.379097248909,"screenshot":"https://user-gold-cdn.xitu.io/2019/7/29/16c3d626e697b4cd?w=550&h=367&f=jpeg&s=33903","content":"娱乐圈的瓜真的是一波又一波，这次又轮到文章和马伊琍了。他们具体为啥会婚变，咱也不知道，啥也不敢问，啥也不干说。不过他们微博下面还是开锅了，下面就一起来看看吧。 首先我们先来看看微博页面，爬虫要从何处下手。 总共有4各参数，ajwvr、id、from 和 __rnd。 至此，我们…","summaryInfo":null,"category":{"name":"后端","id":"5562b419e4b00c57d9b94ae2"},"tags":[{"id":"559a7227e4b08a686d25744f","title":"Python"}],"title":"惊闻马大姐婚变，我连夜爬了微博评论，沦陷","type":"post","user":{"id":"5c4522cde51d45299a08a681","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2019/6/26/16b927bc8120974f","username":"周萝卜"},"lastCommentTime":"2019-07-30T10:29:45.336Z","likeCount":5,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:42:33.814Z","updatedAt":"2019-07-30T02:29:48.440Z"}},{"node":{"id":"5d3f95a8f265da03ad142991","commentsCount":2,"hot":false,"hotIndex":10.4691,"original":true,"originalUrl":"https://juejin.im/post/5d3f95a8f265da039e12959d","rankIndex":10.078119441043,"screenshot":"","content":"随着微服务的流行，服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点，从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性,分布式系统的流量防卫兵。 QQ: 2270033969 一起来聊聊你们是咋用 spring cloud 的吧。","summaryInfo":null,"category":{"name":"后端","id":"5562b419e4b00c57d9b94ae2"},"tags":[{"id":"559a7207e4b08a686d25703e","title":"Java"}],"title":"Spring Cloud Gateway  扩展支持动态限流","type":"post","user":{"id":"589f05e1128fe1006ce71e21","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2018/5/28/163a6fd4a30b231e?w=540&h=540&f=jpeg&s=19751","username":"冷冷gg"},"lastCommentTime":"2019-07-30T09:21:23.616Z","likeCount":5,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:53:58.392Z","updatedAt":"2019-07-30T02:23:19.479Z"}},{"node":{"id":"5d3fa16df265da039a2860f9","commentsCount":0,"hot":false,"hotIndex":4.8179,"original":true,"originalUrl":"https://juejin.im/post/5d3fa101f265da03a53a11a1","rankIndex":8.0404483208405,"screenshot":"","content":"最近观察项目 CI 跑的情况如何时，会偶尔发现一两个镜像虽然构建成功但是容器跑不起来的情况。究其原因，是因为一个 exit code 的问题 exit code 代表一个进程的返回码，通过系统调用 exit_group 来触发。在 POSIX 中，0 代表正常的返回码，而 1-…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"55644032e4b03286789d7528","title":"Docker"}],"title":"throw Error 与 Promise.reject 区别以及在 docker 中的问题","type":"post","user":{"id":"56a34361816dfa005925a654","role":"editor","avatarHd":null,"avatarLarge":"https://leancloud-gold-cdn.xitu.io/bdfecd06f90e24f88946.jpeg?imageView/2/w/100/h/100/q/80/format/png","username":"shanyue"},"lastCommentTime":null,"likeCount":2,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:46:21.201Z","updatedAt":"2019-07-30T02:22:16.028Z"}},{"node":{"id":"5d3f10c26fb9a06b2442f5f3","commentsCount":0,"hot":false,"hotIndex":14.2416,"original":true,"originalUrl":"https://juejin.im/post/5d3f09d5f265da039134ee35","rankIndex":7.0293803794228,"screenshot":"","content":"Dart是一门新的编程语言，如同JAVA、PHP一样，是为了解决编写应用程序中的一些实际问题而被造轮子发明出来的，而这个造轮子的人就是 Google。可能大家都熟悉Google 的另一个轮子Golang，而对 Dart 听闻甚少，其实Dart 的出生跟Go很相近，只是由于它的星…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"5a962a8051882571faa854ed","title":"Dart"}],"title":"Dart 要想飞的高基础要打牢篇一(变量与操作符)","type":"post","user":{"id":"5b3b8d03e51d451964620580","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2019/7/25/16c2933facf6e08c?w=1239&h=1209&f=png&s=1164333","username":"praise"},"lastCommentTime":null,"likeCount":2,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:35:46.990Z","updatedAt":"2019-07-30T02:32:30.651Z"}},{"node":{"id":"5d3ee28e6fb9a06aee360a23","commentsCount":0,"hot":false,"hotIndex":5.3451,"original":true,"originalUrl":"https://juejin.im/post/5d3ee2545188255d845ff50e","rankIndex":7.9424618041394,"screenshot":"","content":"示例代码基于 AndFix，NuWa，Robust 进行了调整，抽取主要部分用来讲解原理。 插件化和热修复的原理，都是动态加载 dex／apk 中的类／资源，两者的目的不同。插件化目标在于加载 activity 等组件，达到动态下发组件的功能，热修复目标在修复已有的问题。目标不…","summaryInfo":null,"category":{"name":"Android","id":"5562b410e4b00c57d9b94a92"},"tags":[{"id":"5597838ee4b08a686ce2319d","title":"Android"}],"title":"【Android 修炼手册】常用技术篇 -- Android 热修复解析","type":"post","user":{"id":"58d9d015ac502e0058df1f96","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2017/6/7/31e5c1610cfd6982bb9d49db821d97f0","username":"ZY5A59"},"lastCommentTime":null,"likeCount":2,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:58:03.681Z","updatedAt":"2019-07-30T02:26:55.205Z"}},{"node":{"id":"5d3f00d0f265da03b46bc710","commentsCount":0,"hot":false,"hotIndex":6.9274,"original":true,"originalUrl":"https://juejin.im/post/5d3f00aaf265da03e1685097","rankIndex":7.3623198074749,"screenshot":"","content":"此处源码是将该 Topic 的订阅信息找出来，然而这里却没找到，所以报了消费订阅不存在的错误。 朋友还跟我讲了他的消费集群中，每个消费者订阅了自己的 Topic，他的消费组中 有 c1 和 c2 消费者，c1 订阅了 topicA，而 c2 订阅了 topicB。 这意味着集群…","summaryInfo":null,"category":{"name":"后端","id":"5562b419e4b00c57d9b94ae2"},"tags":[{"id":"5bffaa29518825787d33db94","title":"RocketMQ"}],"title":"RocketMQ为什么要保证订阅关系的一致性？","type":"post","user":{"id":"58dd3291ac502e006cf4f1b9","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2019/7/6/16bc5aa53d6a25ae?w=500&h=500&f=png&s=14491","username":"后端进阶"},"lastCommentTime":null,"likeCount":4,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:53:15.357Z","updatedAt":"2019-07-30T02:28:28.239Z"}},{"node":{"id":"5d3f0ec66fb9a06acd44faae","commentsCount":0,"hot":false,"hotIndex":17.3178,"original":true,"originalUrl":"https://juejin.im/post/5d3eca7ce51d4561d54de8e1","rankIndex":7.2110945230439,"screenshot":"","content":"React Hooks 自推出之后，收到了不少追捧， 很多问题也随之而来。 我认为： 不会. 在我看来，相比于传统的Class Component, Hooks 并没有提供什么新的状态功能，只不过是对原有的 API 做了增强。 相比之前����Hoos 更加简洁，也提升了原生 API…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"555e99ffe4b00c57d99556aa","title":"React.js"}],"title":"[译] React Hooks  越来越火了，它会取代传统的 Redux 吗？","type":"post","user":{"id":"57c440ae5bbb500063457149","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2019/6/22/16b7ce3b90ea3cf1?w=748&h=750&f=png&s=716921","username":"皮蛋是条猪"},"lastCommentTime":null,"likeCount":4,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:35:07.646Z","updatedAt":"2019-07-30T02:22:43.779Z"}},{"node":{"id":"5d3f2ca46fb9a06b30701aaf","commentsCount":1,"hot":false,"hotIndex":9.1257,"original":true,"originalUrl":"https://juejin.im/post/5d3f2c65f265da03f66d99a0","rankIndex":7.0216235877528,"screenshot":"","content":"DailyENJS 致力于翻译优秀的前端英文技术文章，为技术同学带来更好的技术视野。 ECMAScript 2015，也称为ES6，是一个花了六年时间才完成的主要版本。从那时起，负责制定ECMAScript标准的 TC39 每年都会发布新版本的标准。这个年度发布周期简化了流程，…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"5597a05ae4b08a686ce56f6f","title":"前端"}],"title":"【DailyENJS第3期】5个你现在可以使用的 ES2019 特性","type":"post","user":{"id":"5894886f2f301e00693a3e49","role":"guest","avatarHd":null,"avatarLarge":"https://mirror-gold-cdn.xitu.io/168e083fdfcb151db8a","username":"_忽如寄"},"lastCommentTime":"2019-07-30T10:14:53.729Z","likeCount":2,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:36:30.161Z","updatedAt":"2019-07-30T02:27:45.786Z"}},{"node":{"id":"5d3eb96be51d4561ff66679f","commentsCount":1,"hot":false,"hotIndex":4.6549,"original":true,"originalUrl":"https://juejin.im/post/5d3eb914e51d4561f95ee9b0","rankIndex":5.028572452897,"screenshot":"","content":"现在流行 mvvm 三大框架，各种cli 工具也给我们提供了很多方便。我在工作中使用的是vue 技术栈。vue-cli 让我不能更爽了。分分钟拉起架子，开始各种业务代码。 但是，工作中我还遇到另一种情况，就是我需要写一些 SDK 文件，有对内的也有对外的。每次写这个都让我蛋疼的…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"55c8daed60b2d1400fde7bc7","title":"Gulp"}],"title":"【构建】我用gulp定制了一个SDK脚手架","type":"post","user":{"id":"59bc8da66fb9a00a4c26f53a","role":"guest","avatarHd":null,"avatarLarge":"https://mirror-gold-cdn.xitu.io/168e0891122417aa61b","username":"yjua"},"lastCommentTime":"2019-07-29T18:54:42.845Z","likeCount":1,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T02:07:41.655Z","updatedAt":"2019-07-30T02:32:31.112Z"}},{"node":{"id":"5d3ee5345188255d8b6c5376","commentsCount":0,"hot":false,"hotIndex":3.5469,"original":true,"originalUrl":"https://juejin.im/post/5d3ee1c4e51d4562092387ce","rankIndex":5.8580536457451,"screenshot":"","content":"SideBar是APP开发当中常见的功能之一，多用于索引列表，如城市选择，分类等。在优化OpenGit趋势列表时，由于在选择语言时需要用到这样的控件，尝试开发了这个控件，效果如下图所示 上文代码，没有做过多的操作，只是定义了几个变量，详细的操作在_SlideItemBarSta…","summaryInfo":null,"category":{"name":"Android","id":"5562b410e4b00c57d9b94a92"},"tags":[{"id":"5a96291f6fb9a0535b535438","title":"Flutter"}],"title":"Flutter侧边栏控件-SideBar","type":"post","user":{"id":"56ea9d7ca341310054a57b7c","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2019/4/30/16a6d0a13eb40f4e?w=1242&h=1227&f=png&s=722972","username":"Yuzo"},"lastCommentTime":null,"likeCount":1,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:58:16.867Z","updatedAt":"2019-07-30T02:22:15.507Z"}},{"node":{"id":"5d3f93565188255d6b3c2f5a","commentsCount":0,"hot":false,"hotIndex":5.6075,"original":true,"originalUrl":"https://juejin.im/post/5d3f92356fb9a06b317b3baf","rankIndex":5.6118560824318,"screenshot":"https://user-gold-cdn.xitu.io/2019/7/30/16c4057375104138?w=474&h=316&f=jpeg&s=10466","content":"你喜欢写文档吗？ 我喜欢。 所以说文档成了开发心中的一个痛。尤其是使用 restful 接口，成了必须要写文档，否者前端同学根本不知道你写了什么。那么让我写文档，还不如杀了我呢！！！ Swagger 是一个 API 生成工具，可以生成文档。 Swagger 是通过编写 yaml…","summaryInfo":null,"category":{"name":"后端","id":"5562b419e4b00c57d9b94ae2"},"tags":[{"id":"555e9a80e4b00c57d9955de2","title":"Go"}],"title":"Gin(十):集成 Swagger","type":"post","user":{"id":"582c029e2e958a0069b1feb2","role":"guest","avatarHd":null,"avatarLarge":"https://mirror-gold-cdn.xitu.io/168e08377ce46595adb","username":"youngxhui"},"lastCommentTime":null,"likeCount":3,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:53:43.140Z","updatedAt":"2019-07-30T02:24:41.417Z"}},{"node":{"id":"5d3ed512f265da03970b9291","commentsCount":0,"hot":false,"hotIndex":2.0778,"original":true,"originalUrl":"https://juejin.im/post/5d3ed4aaf265da03e61ae949","rankIndex":5.5180070257135,"screenshot":"","content":"蚂蚁金服的业务数据库起初是单库单表，但随着业务数据规模的快速发展，数据量越来越大，单库单表逐渐成为瓶颈。所以我们对数据库进行了水平拆分，将原单库单表拆分成数据库分片。 如下图所示，分库分表之后，原来在一个数据库上就能完成的写操作，可能就会跨多个数据库，这就产生了跨数据库事务问题…","summaryInfo":null,"category":{"name":"阅读","id":"5562b428e4b00c57d9b94b9d"},"tags":[{"id":"5bf95decf265da3ff4cc84cd","title":"分布式"}],"title":"蚂蚁金服大规模分布式事务实践和开源历程","type":"post","user":{"id":"5b4c1554f265da0f574ddb33","role":"guest","avatarHd":null,"avatarLarge":"https://mirror-gold-cdn.xitu.io/168e091faa206f6faa0","username":"蚂蚁金服科技"},"lastCommentTime":null,"likeCount":1,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T02:10:00.426Z","updatedAt":"2019-07-30T02:24:53.687Z"}},{"node":{"id":"5d3ef1936fb9a06b2766a4bd","commentsCount":0,"hot":false,"hotIndex":0.8777,"original":true,"originalUrl":"https://juejin.im/post/5d3ef0386fb9a06b031fd6c2","rankIndex":5.1692576448021,"screenshot":"","content":"读完第二遍之后，我们需要选择是否要进行第三遍精读。大多数的书，读完前两遍就已经足够，因此开始精读之前，我们要先想想是否值得在这本书上花时间。 我们可以通过以下方法，做到从精读到最终输出，将一本书的价值最大化。 也许你会发现，经常看完一本书之后，脑子里只留下了一些模糊的概念。有人…","summaryInfo":null,"category":{"name":"阅读","id":"5562b428e4b00c57d9b94b9d"},"tags":[{"id":"55c1748160b28fd99e49ea68","title":"程序员"}],"title":"怎样成为快速阅读的高手（下）","type":"post","user":{"id":"57c60e8d8ac24700635a02a7","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2018/12/8/1678c718011a10b3?w=506&h=506&f=png&s=253275","username":"LeeChen"},"lastCommentTime":null,"likeCount":0,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T02:10:41.322Z","updatedAt":"2019-07-30T02:22:37.435Z"}},{"node":{"id":"5d3f883ae51d4561b674c3c2","commentsCount":0,"hot":false,"hotIndex":5.5461,"original":true,"originalUrl":"https://juejin.im/post/5d3f878fe51d4561ff6667a4","rankIndex":4.4424731988629,"screenshot":"","content":"今天我们很高兴为Babel用户宣布一些特别的东西。一年前，我们开始着手发现用户在使用TypeScript时遇到的最大困难，我们发现Babel用户的一个共同问题是尝试设置好TypeScript 太难了。 原因通常各不相同，但对于许多开发人员来说，重写已经正在使用的构建配置可能是一…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"58a3deef8d6d810057e64970","title":"Babel"}],"title":"[译]TypeScript 和 Babel 7","type":"post","user":{"id":"5af6d287f265da0b776fc565","role":"guest","avatarHd":null,"avatarLarge":"https://user-gold-cdn.xitu.io/2019/4/7/169f51cfc059e004?w=180&h=180&f=png&s=15624","username":"前端小纠结"},"lastCommentTime":null,"likeCount":1,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-30T01:37:35.083Z","updatedAt":"2019-07-30T02:32:30.406Z"}}],"pageInfo":{"hasNextPage":true,"endCursor":"5.1097955801374999"}}}}}';
var jsonFromJuejinZipped =
    '{"data":{"articleFeed":{"items":{"edges":[{"node":{"id":"5d3f84376fb9a06b2c326988","commentsCount":10,"hot":false,"hotIndex":161.2088,"original":true,"originalUrl":"https://juejin.im/post/5d3f8402f265da039e129574","rankIndex":23.480145447961,"screenshot":"","content":"为了保证的可读性，本文采用意译而非直译。 BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值。在对大整数执行数学运算时，以任意精度表示整数的能力尤为重要。使用BigInt，整数溢出将不再是问题。 此外，可以安全地使用更加准确时间戳，大整数ID等，而无需使用…","summaryInfo":null,"category":{"name":"前端","id":"5562b415e4b00c57d9b94ac8"},"tags":[{"id":"55964d83e4b08a686cc6b353","title":"JavaScript"}],"title":"JS 即将到来的第八种基本类型:BigInt","type":"post","user":{"id":"59df61ec51882578ce26ee6e","role":"guest","avatarHd":null,"avatarLarge":"https://mirror-gold-cdn.xitu.io/168e08a02f4dda88289","username":"前端小智"},"lastCommentTime":"2019-07-30T10:24:11.927Z","likeCount":25,"eventInfo":null,"viewerHasLiked":false,"createdAt":"2019-07-29T23:41:43.557Z","updatedAt":"2019-07-30T02:30:00.069Z"}}],"pageInfo":{"hasNextPage":true,"endCursor":"5.1097955801374999"}}}}}';

void main() {
  group('ZIP', () {
    testZipList();
    testZipMap();
    testLarge();
  });

  /// 掘金首页上拿到的一个比较大的JSON：[jsonFromJuejin]
  /// zip以后[jsonFromJuejinZipped]
  group('CONVERT BETWEEN ZIPPED OR NOT', () {
    var clazz = Clazz.fromJson(jsonFromJuejin).toString();
    var zipMap = zip(jsonDecode(jsonFromJuejin));
    var clazzZipped = Clazz.fromMap(zipMap).toString();
    var clazzZipped2 = Clazz.fromJson(jsonFromJuejinZipped).toString();

    test('convert', () {
      print(clazz);
      // print(clazzZipped);
      expect(clazz, equals(clazzZipped));
      expect(clazzZipped, equals(clazzZipped2));
    });
  });
}

void testLarge() {
  var zipped = zip(jsonDecode(jsonFromJuejin));

  test('LARGE', () {
    expect(zipped.containsKey('data'), true);
    zipped = zipped['data'];
    expect(zipped.containsKey('articleFeed'), true);
    zipped = zipped['articleFeed'];
    expect(zipped.containsKey('items'), true);
    zipped = zipped['items'];
    expect(zipped.containsKey('pageInfo'), true);
    expect(zipped['pageInfo'].containsKey('hasNextPage'), true);
    expect(zipped['pageInfo'].containsKey('endCursor'), true);
    expect(zipped.containsKey('edges'), true);
    zipped = zipped['edges'][0];
    expect(zipped.containsKey('node'), true);
  });
}

void testZipList() {
  // {a: true, b: 1, c: OK, d: {e: 0, f: 1}, g: [{h: 1, j: 3, i: 2, k: 4}]}
  test('zipped json list contains all keys', () {
    Map zipped = zip(jsonDecode(jsonList))[0];
    expect(zipped.containsKey('a'), true);
    expect(zipped.containsKey('b'), true);
    expect(zipped.containsKey('c'), true);
    expect(zipped.containsKey('d'), true);
    expect(zipped['d'].containsKey('e'), true);
    expect(zipped['d'].containsKey('f'), true);
    expect(zipped.containsKey('g'), true);
    expect(zipped['g'][0].containsKey('h'), true);
    expect(zipped['g'][0].containsKey('i'), true);
    expect(zipped['g'][0].containsKey('j'), true);
    expect(zipped['g'][0].containsKey('k'), true);
  });
}

void testZipMap() {
  // {root: [{a: true, b: 1, c: OK, d: {e: 0, f: 1}, g: [{h: 1, j: 3, i: 2, k: 4}]}]}
  var zipped = zip(jsonDecode(jsonMap));
  test('zipped json map contains all keys', () {
    expect(zipped.containsKey('root'), true);
    zipped = zipped['root'][0];
    expect(zipped.containsKey('a'), true);
    expect(zipped.containsKey('b'), true);
    expect(zipped.containsKey('c'), true);
    expect(zipped.containsKey('d'), true);
    expect(zipped['d'].containsKey('e'), true);
    expect(zipped['d'].containsKey('f'), true);
    expect(zipped.containsKey('g'), true);
    expect(zipped['g'][0].containsKey('h'), true);
    expect(zipped['g'][0].containsKey('i'), true);
    expect(zipped['g'][0].containsKey('j'), true);
    expect(zipped['g'][0].containsKey('k'), true);
  });
}
